<template>
  <div id="terminal" ref="terminal"></div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import { Terminal } from 'xterm';
import { FitAddon } from 'xterm-addon-fit';
import 'xterm/css/xterm.css';
import {connect, disconnect, sendMessage} from "../websocket.js";

// 定义交互式命令列表
const INTERACTIVE_COMMANDS = [
    'vim', 'vi', 'nano', 'less', 'more', 'top', 'htop'
];

const terminal = ref(null);
const stompClient = ref(null);
// const rows = 40;
const cols = 100;
let commandBuffer = "";
const commandHistory = [];
let historyIndex = 0;
let suggestions = [];
let suggestionIndex = -1;

const sessionId = ref(crypto.randomUUID());
const isInteractiveMode = ref(false);

onMounted(() => {
  connect(res => {
    console.log(res);
    if (res.type === 'interactive') {
      // 处理交互式命令的输出
      if (res.output) {
        writeShell(res.output);
      }
      if (res.error) {
        writeShell(res.error);
      }
    } else if (res.suggestions) {
      suggestions = res.suggestions;
      if (suggestions.length > 0) {
        if (suggestions.length === 1) {
          const completion = suggestions[0];
          const lastWord = commandBuffer.split(' ').pop();
          const toAdd = completion.slice(lastWord.length);
          writeShell(toAdd);
          commandBuffer += toAdd;
        } else {
          writeShell('\r\n');
          writeShell(suggestions.join('  '));
          writeShell('\r\n');
          prompt();
          writeShell(commandBuffer);
        }
      }
    } else if (res.output) {
      console.log(res.output);
      writeShell(res.output)
      prompt();
    } else if (res.error) {
      console.log(res.error);
      writeShell(res.error)
      prompt();
    }
  }, sessionId.value);
  initXterm();
});

let height = document.body.clientHeight;
let rows = parseInt(height/18);//18是字体高度,根据需要自己修改

const initXterm = () => {
  const term = new Terminal({
    rendererType: 'canvas',
    rows,
    // cols,
    convertEol: true,
    disableStdin: false,
    cursorBlink: true,
    theme: {
      foreground: '#ECECEC',
      background: '#000000',
      cursor: 'help',
      lineHeight: 20,
    },
  });

  term.open(terminal.value);
  const fitAddon = new FitAddon();
  term.loadAddon(fitAddon);
  fitAddon.fit();

  window.addEventListener('resize', resizeScreen);

  function resizeScreen() {
    fitAddon.fit();
  }

  let compositionText = '';

  terminal.value.addEventListener('compositionstart', (e) => {
    compositionText = '';
  });

  terminal.value.addEventListener('compositionend', (e) => {
    const finalText = e.data;
    commandBuffer += finalText;
    writeShell(finalText);
  });

  // 修改 onKey 事件处理
  term.onKey((event) => {
    if (event.domEvent.isComposing) {
      return;
    }
    terminalOnKey(event);
  });

  terminal.value = term;
  runFakeTerminal();
};

const runFakeTerminal = () => {
  const term = terminal.value;
  if (term._initialized) return;
  term._initialized = true;
  writeShell("Welcome to \x1b[1;32m墨天轮\x1b[0m.");
  writeShell("\r\n")
  writeShell('This is Web Terminal of Modb; Good Good Study, Day Day Up.');
  prompt();
};

const prompt = () => {
  writeShell('\r\n\x1b[33m$\x1b[0m ');
};

const writeShell = (data) => {
  console.log("writeShell" + data);
  terminal.value.write(data);
};

function checkCtrlKeyAllSystem(domEvent) {
  const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
  const isPressCtrlKey = isMac ? domEvent.metaKey : domEvent.ctrlKey;
  return isPressCtrlKey;

}

function terminalOnKey(event) {
  const ctrlKey = checkCtrlKeyAllSystem(event.domEvent);
  console.log("keyDown", event.domEvent.key);

  // 回车键
  if (event.domEvent.key === 'Enter') {
    console.log("Enter", commandBuffer);
    commandHistory.push(commandBuffer);

    // 判断是否是交互式命令
    const baseCommand = commandBuffer.split(/\s+/)[0];
    if (INTERACTIVE_COMMANDS.includes(baseCommand)) {
      isInteractiveMode.value = true;
      sendMessage({
        type: 'interactive',
        command: commandBuffer,
        sessionId: sessionId.value
      });
    } else if (isInteractiveMode.value) {
      // 如果已经在交互模式中
      sendMessage({
        type: 'interactive_input',
        command: commandBuffer,
        sessionId: sessionId.value
      });
    } else {
      // 普通命令
      sendMessage({
        type: 'command',
        command: commandBuffer
      });
    }

    commandBuffer = '';
    writeShell("\r\n");
    if (!isInteractiveMode.value) {
      prompt();
    }
  } else if (event.domEvent.key === 'Tab') {
    event.domEvent.preventDefault();
    
    if (!commandBuffer.trim()) {
      return;
    }

    sendMessage({
      type: 'completion',
      command: commandBuffer
    });
  } else if (event.domEvent.key === 'Backspace') {
    // 处理退格键
    if (commandBuffer.length > 0) {
      commandBuffer = commandBuffer.slice(0, -1);
      terminal.value.write('\b \b');
    }
    event.domEvent.preventDefault();
  } else if (event.domEvent.key === 'Delete') {
    // 处理删除键
    if (commandBuffer.length > 0) {
      commandBuffer = commandBuffer.slice(0, -1);
      terminal.value.write('\b \b');
    }
    event.domEvent.preventDefault();
  } else if (event.domEvent.key === 'ArrowUp') {
    console.log("ArrowUp", commandHistory);
    historyIndex--;
    const command = commandHistory.at(historyIndex);
    console.log(command);
    if (command) {
      // 清空当前行内容
      terminal.value.write('\r');
      terminal.value.write('\x1b[K'); // 清除从光标到行尾的内容
      prompt();
      commandBuffer = command;
      writeShell(command);
    }
    // 阻止事件默认行为
    event.domEvent.preventDefault();
  } else if (event.domEvent.key === 'ArrowDown') {
    historyIndex++;
    const command = commandHistory[historyIndex];
    console.log(command);
    if (command) {
      // 清空当前行内容
      terminal.value.write('\r');
      terminal.value.write('\x1b[K'); // 清除从光标到行尾的内容
      prompt();
      commandBuffer = command;
      writeShell(command);
    }
    // 阻止事件默认行为
    event.domEvent.preventDefault();
  } else if (ctrlKey && event.domEvent.key === 'c') {
    // ...
    commandBuffer = '';
    prompt();
  } else if (ctrlKey && domEvent.shiftKey && event.domEvent.key === 'a') {
    // ...
  } else if (!event.domEvent.altKey && !event.domEvent.ctrlKey && !event.domEvent.metaKey && event.key.length === 1) {
    // 处理普通字符输入
    writeShell(event.key);
    commandBuffer += event.key;
  }
}

const sentFirst = () => {
  const _bar = {
    operate: 'connect',
    host: '***',
    port: 22,
    username: '***',
    password: '***',
    userId: 1024,
  };
  stompClient.value.send('/msg', {}, JSON.stringify(_bar));
};

onUnmounted(() => {
  if (isInteractiveMode.value) {
    sendMessage({
      type: 'terminate',
      sessionId: sessionId.value
    });
  }
  disconnect();
});
</script>

<style>
#terminal {
  width: 100%;
  height: 100%;
  text-align: left;
}
</style>